/* QtLua -- Lua bindings for Qt
   Copyright (C) 2011, Jarek Pelczar

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General
   Public License along with this library; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301 USA

*/

#ifndef QLUAGLOBAL_H
#define QLUAGLOBAL_H

#include <QObject>
#include <QVariant>
#include "qluascriptvalue.h"

class QLuaScriptEngine;
class QLuaScriptValue;

QLuaScriptEngine * qluaEngine(QObject *);

namespace QLuaInternal {

struct QLuaMetaTypeRegistryEntry
{
    typedef QLuaScriptValue (* ToValue)(QLuaScriptEngine *, const void *);
    typedef void (* FromValue)(const QLuaScriptValue&, void *);    
    typedef void (* Construct)(void * ptr, const void * other);
    typedef void (* Destruct)(void *);

    int m_typeId;
    int m_objSize;
    ToValue m_toScriptFunc;
    FromValue m_fromScriptFunc;
    Construct m_construct;
    Destruct m_destruct;
    QLuaScriptValue m_prototype;
};

template<typename T> class CtorHelpers
{
public:
    static void Construct(void * ptr, const void * other)
    {
        if(other)
            new(ptr) T(*(const T*)other);
        else
            new(ptr) T();
    }

    static void * NewClass(void * p)
    {
        return new(p) T();
    }

    static void Destruct(void * ptr)
    {
        ((T *)ptr)->~T();
    }
};

void registerLuaType(QLuaScriptEngine * engine, QLuaMetaTypeRegistryEntry * entry);

}

template<typename T> int qluaRegisterScriptMetaType(QLuaScriptEngine * engine,
                                                    QLuaScriptValue (* toScriptValue)(QLuaScriptEngine * engine, const T * t),
                                                    void (* fromScriptValue)(const QLuaScriptValue& value, T * t),
                                                    const QLuaScriptValue& prototype = QLuaScriptValue())
{
    static QLuaInternal::QLuaMetaTypeRegistryEntry registry_entry = {
        qMetaTypeId<T>(),
        sizeof(T),
        (QLuaInternal::QLuaMetaTypeRegistryEntry::ToValue)toScriptValue,
        (QLuaInternal::QLuaMetaTypeRegistryEntry::FromValue)fromScriptValue,
        QLuaInternal::CtorHelpers<T>::Construct,
        QLuaInternal::CtorHelpers<T>::Destruct,
        prototype
    };

    QLuaInternal::registerLuaType(engine, &registry_entry);

    return registry_entry.m_typeId;
}

#endif // QLUAGLOBAL_H
